package com.hillky.channelhandler.handler;

import com.hillky.compress.Compressor;
import com.hillky.compress.CompressorFactory;
import com.hillky.serialize.Serializer;
import com.hillky.serialize.SerializerFactory;
import com.hillky.transport.message.MessageFormatConstant;
import com.hillky.transport.message.YrpcResponse;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import lombok.extern.slf4j.Slf4j;

/**
 * 基于长度字段的帧解码器
 *    * <pre>
 *    *   0    1    2    3    4    5    6    7    8    9    10   11   12   13   14   15   16   17   18   19   20   21   22
 *    *   +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
 *    *   |    magic          |ver |head  len|    full length    |code| ser|comp|              RequestId                |
 *    *   +-----+-----+-------+----+----+----+----+-----------+----- ---+--------+----+----+----+----+----+----+---+---+
 *    *   |                                                                                                             |
 *    *   |                                         body                                                                |
 *    *   |                                                                                                             |
 *    *   +--------------------------------------------------------------------------------------------------------+---+
 *    * </pre>
 */
@Slf4j
public class YrpcResponseDecoder extends LengthFieldBasedFrameDecoder {
    public YrpcResponseDecoder() {
        super(
                // 找到当前报文的总长度，截取报文，截取出来的报文我们可以去进行解析
                //最大帧的长度，超过这个值就会丢弃
                MessageFormatConstant.MAX_FRAME_LENGTH,
                // 长度字段偏移量
                MessageFormatConstant.MAGIC.length+MessageFormatConstant.VERSION_LENGTH+MessageFormatConstant.HEADER_FIELD_LENGTH,
                // 长度字段的长度
                MessageFormatConstant.FULL_FIELD_LENGTH,
                // todo 负载的适配长度
                -(MessageFormatConstant.MAGIC.length+MessageFormatConstant.VERSION_LENGTH+MessageFormatConstant.HEADER_FIELD_LENGTH+MessageFormatConstant.FULL_FIELD_LENGTH),
                0);
    }


    @Override
    protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
        Object decode = super.decode(ctx, in);

        if(decode instanceof ByteBuf byteBuf){
            //自动转换bytebuf

            return decodeFrame(byteBuf);
        }
        return null;
    }

    private Object decodeFrame(ByteBuf byteBuf) {
        //1. 解析魔数值
        byte[] magic=new byte[MessageFormatConstant.MAGIC.length];
        byteBuf.readBytes(magic);
        // 检测魔数是否匹配
        for (int i = 0; i < magic.length; i++) {
            if(magic[i]!=MessageFormatConstant.MAGIC[i]){
//                throw new RuntimeException("获得的请求不合法");
                throw new RuntimeException("The request obtained is not legitimate");
            }
        }

        //2. 解析版本号
        byte version = byteBuf.readByte();
        if(version>MessageFormatConstant.VERSION){
            throw new RuntimeException("获得的请求版本不被支持");
        }

        //3. 解析头部长度
        short headerLength = byteBuf.readShort();

        //4、解析总长度
        int fullLength = byteBuf.readInt();

        //5. 请求类型 todo 判断是不是心跳检测
        byte responseCode = byteBuf.readByte();

        //6. 序列化类型
        byte serializeType = byteBuf.readByte();

        //7. 压缩类型
        byte compressType = byteBuf.readByte();

        //8. 请求id
        long requestId = byteBuf.readLong();

        //8. 时间戳
        long timeStamp = byteBuf.readLong();

        // 我们需要封装
        YrpcResponse yrpcResponse = new YrpcResponse();
        yrpcResponse.setCode(responseCode);
        yrpcResponse.setCompressType(compressType);
        yrpcResponse.setSerializeType(serializeType);
        yrpcResponse.setRequestId(requestId);
        yrpcResponse.setTimeStamp(timeStamp);


        // todo  心跳请求没有负载，此处可以判断并且直接返回
//        if(requestType== RequestType.HEART_BEAT.getId()){
//            return yrpcRequest;
//        }


        //9.请求载体
        int bodyLength=fullLength-headerLength;
        byte[] payload=new byte[bodyLength];
        byteBuf.readBytes(payload);

        if(payload.length>0){
            //有了字节数组后，就可以解压缩，反序列化
            //  解压缩
            Compressor compressor = CompressorFactory.getCompressor(yrpcResponse.getCompressType()).getImpl();
            payload=compressor.deCompress(payload);


            // 反序列化
            Serializer serializer = SerializerFactory.getSerializer(yrpcResponse.getSerializeType()).getImpl();
            Object body = serializer.deserialize(payload, Object.class);
            yrpcResponse.setBody(body);
        }




        if(log.isDebugEnabled()){
            log.debug("响应【{}】已经在调用端完成解码工作",yrpcResponse.getRequestId());
        }

        return yrpcResponse;

    }
}
